package aquabelva;

/**
 * The MetaDataLogger class provides a metadata logging object to assist in logging errors
 * and general information about WebTalk pages. A method to log this data to file is
 * made available.
 * @author Edwe Cowley (Aqua Belva)
 */

import java.util.*;
import java.io.*;

public class MetaDataLogger {

  private int lineCount = -1;                    //Number of lines in WebTalk source file
  private long fileSize = -1;                    //File size of WebTalk source file
  private long translateTime = -1;               //Time taken to translate page in milliseconds
  private Vector <WebTalkError> errors;          //A Vector of errors
  private Vector <String> messages;              //A Vector of messages
  private Vector <String> filesTranslated;       //A Vector of all files translated
  private String tempFile = "translatetemp.txt"; //Temporary file to store WebTalk String
  
  /**
   * The default constructor
   */	
  public MetaDataLogger () {
	  errors = new Vector <WebTalkError>();
	  messages = new Vector <String>();
	  filesTranslated = new Vector <String>();
  }

  /**
   * @return a List of all WebTalkErrors in the WebTalk source
   */	
  public List getErrors() {
	
	  return errors;
  }
  
  /**
   * Get line count and file size metadata for the main file from WebTalk String.
   * This is useful for adding the main WebTalk page (i.e. not a nested file) 
   * metadata, as file size and line count from nested children can easily be added 
   * to the data later using addSizeMetaData (String file) to calculate effective totals.
   *
   * @param wtStr the WebTalk String from which metadata must be gathered
   * @return true on success, false on failure
   */
  public boolean addSizeMetaDataFromString (String wtStr) {
	try {
	  BufferedWriter out = new BufferedWriter(new FileWriter(tempFile));
	  out.write (wtStr);
	  out.flush();
	  out.close();
	      
	  boolean succeed = addSizeMetaData (tempFile);
	      
	  if(!succeed)
	    return false;
	}  
	  catch (IOException e) {
	    return false;
	  }
	
	filesTranslated.add("main page");
	
	/*Try to delete the temporary file and hope it works, but, if not,
	 *it doesn't really matter as it will be overwritten later anyway.*/
	try {
      File toDel = new File (tempFile);
      if (toDel.exists())
        toDel.delete();
	}
	  catch (Exception ex) {
	    this.logError("Metadata logging error: could not delete temporary file, " + tempFile);
	    return false;
	  }
	  
    return true;
  }
  
  /**
   * Get line count and file size metadata from file and add it to
   * the file size and line numbers recorded previously. This is useful
   * for files with nesting, as file size and line count from nested children
   * can easily be added to the data from the parent to calculate effective
   * totals. Additionally, this method adds the file to the list of local files
   * accessed.
   * 
   * @param file the absolute path of the file
   * @return true on success, false on failure
   */
  public boolean addSizeMetaData (String file) {
	if(lineCount == -1) 
      lineCount = 0;
	
	if(fileSize == -1) 
	      fileSize = 0;
	
	long bytes = 0;
	int lin = 0;
	
	File f = new File (file);
	if (f.exists()) {
      try {
	    BufferedReader br = new BufferedReader(new FileReader(file));
	    while (br.readLine() != null) 
	     lin++; 
	    
	    bytes = f.length();
	    br.close();
	  }
	  catch (IOException e) {
		this.logError("Could not find nested file: \""+ file +"\"");
        return false;
	  } 
	
	
	fileSize += bytes;
	lineCount += lin;
	
	if (file != tempFile)
	  filesTranslated.add(file);
	} else {
		this.logError("Could not find nested file: \""+ file +"\"");
		return false;
	}
	
	return true;
  }

  /**
   * Log an error
   * @param errorMsg the error message corresponding to this error
   * @param line the line number in which this error was encountered
   */	
  public void logError(String errorMsg, int line) {
    errors.add (new WebTalkError(errorMsg, line));
  }
  
  /**
   * Log an error
   * @param errorMsg the error message corresponding to this error
   */	
  public void logError(String errorMsg) {
	    errors.add (new WebTalkError(errorMsg, -1));
  }
  
  /**
   * @return a List of all messages generated while compiling the WebTalk source
   */	
  public List getMessages() {
	return messages;
  }
  
  /**
   * Log a message
   * @param msg a message to be logged
   */	
  public void logMessage(String msg) {
	    messages.add (msg);
  }

  /**
   * @return the size of the WebTalk source file in bytes
   */	
  public long getFileSize() {
	  return fileSize;
  }

  /**
   * @param size the size of the WebTalk source file in bytes
   */
  public void setFileSize(long size) {
	fileSize = size;
  }

  /**
   * @return the number of lines in the WebTalk source file
   */	
  public int getLineCount() {
	return lineCount;
  }

  /**
   * @param count the number of lines in the WebTalk source file
   */
  public void setLineCount(int count) {
	lineCount = count;
  }
  
  /**
   * Increment the record of the number of lines in the WebTalk source file
   */
  public void incrLineCount() {
	lineCount++;
  }

  /**
   * Decrement the record of the number of lines in the WebTalk source file
   */
  public void decrLineCount() {
	lineCount--;
  }
  
  /**
   * @return the time taken to translate the WebTalk page in milliseconds
   */	
  public long getTranslateTime() {
	return translateTime;
  }

  /**
   * @param time the time taken to translate the WebTalk page in milliseconds
   */
  public void setTranslateTime(long time) {
	translateTime = time;
  }
  
  /**
   * @return a String representation of the metadata
   */
  public String toString() {
	String ret = "";
	
	for (int i = 0; i<errors.size(); i++) {
	  ret += "WebTalk Error: " + errors.elementAt(i).getMessage();
	  
	  if (errors.elementAt(i).getLine() != -1)
		  ret += " (line " + errors.elementAt(i).getLine() + ")";
	
	ret += "\n";
  }
	
	for (int i = 0; i<messages.size(); i++) 
		  ret += messages.elementAt(i) + "\n";
	
	for (int i = 0; i<filesTranslated.size(); i++) 
		  ret += "File processed: " + filesTranslated.elementAt(i) + "\n";
	
	if (lineCount != -1)
	  ret += lineCount + " lines\n";
	
	if (fileSize != -1)
		  ret += fileSize + " bytes\n";
	
	if (translateTime != -1)
		  ret += "Translated in " + translateTime + "ms\n";
	
	return ret;
  }
  
  /**
   * Write the contents of this MetaData object to file
   * @param filename the absolute path of the file to which the output will be dumped
   * @return true on success, false on fail
   */
  public boolean toFile(String filename) {
	  
    String toWrite = this.toString();
    
    try {
      BufferedWriter out = new BufferedWriter(new FileWriter(filename));
      out.write (toWrite);
      out.newLine();
      out.flush();
      out.close();
    }
    catch (IOException e) {
    	return false;
    }
    
    return true;
  }
  
  /**
   * Clear all recorded metadata
   */
  public void reset() {
	errors = new Vector <WebTalkError>();
	messages = new Vector <String>();
	filesTranslated = new Vector <String>();
	lineCount = -1;
	fileSize = -1;
	translateTime = -1;
  }
}
